package sns.websocketservlet;

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;

import sns.app.nhwc.*;

public class NHWCWebSocketServlet extends WebSocketServlet {

private static final long serialVersionUID = 1L;
	
	private static final int ROOM_NUM = 50;

	private static final Set<NHWCGame> games = new CopyOnWriteArraySet<NHWCGame>();

	@Override
	protected StreamInbound createWebSocketInbound(String subProtocol,
			HttpServletRequest request) {
		// get iduser, nickname and gameid
		String iduserStr = request.getParameter("iduser");
		String nickname = request.getParameter("nickname");
		String gameidStr = request.getParameter("gameid");
		if(iduserStr==null||nickname==null||gameidStr==null){
			System.out.println("Invalid parameters!");
			return null;
		}
		int iduser = Integer.parseInt(iduserStr);
		// get the target game
		int gameid = Integer.parseInt(gameidStr);
		NHWCGame game = getGameById(gameid);
		
		return new NHWCMessageInbound(iduser, nickname, game);
	}
	
	public static int getGameId(int roomid){
		if(roomid>ROOM_NUM){
			// roomid exceeds max room id
			// just return an available game
			roomid=-1;
		}
		NHWCGame game;
		if(roomid==-1){
			game = findAvailableGame();
			if(game==null){
				// there is no available game
				System.out.println("There is no available game!");
				return -1;
			}
			return game.getGameId();
		}else{
			game = getGameById(roomid);
			if(game==null){
				// the roomid does not exist
				game = new NHWCGame(roomid);
				games.add(game);
			}
			if(!game.isAvailable()){
				// the game is not available
				return -2;
			}
			return game.getGameId();
		}
	}

	/**
	 * check if the user has already been in a game
	 * @param iduser
	 * @return
	 */
	public static boolean alreadyInGame(int iduser) {
		for (NHWCGame game : games) {
			for(NHWCMessageInbound mib:game.getConnections()){
				if(mib.getIduser()==iduser){
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * get the game of which gameid is roomid
	 * return null if not found
	 * 
	 * @param roomid
	 * @return
	 */
	public static NHWCGame getGameById(int roomid) {
		for (NHWCGame game : games) {
			if(game.getGameId()==roomid){
				return game;
			}
		}
		return null;
	}

	/**
	 * find an available game
	 * if there is no available game, return null
	 * 
	 * @return
	 */
	private static NHWCGame findAvailableGame() {
		for (NHWCGame game : games) {
			if (game.isAvailable()) {
				return game;
			}
		}
		return createNewIdGame();
	}

	/**
	 * create a new game with an unused gameid 
	 * and gameid should not be greater than ROOM_NUM
	 * if gameis is exhausted, return null
	 * @return
	 */
	private static NHWCGame createNewIdGame() {
		NHWCGame game=null;
		for(int i = 1; i <= ROOM_NUM; i++){
			if(getGameById(i)==null){
				// find an unused gameid
				game = new NHWCGame(i);
				games.add(game);
				break;
			}
		}
		return game;
	}
	
	/**
	 * used to get the whole state of all the games
	 * 
	 * @return
	 */
	public static Set<NHWCGame> getGames(){
		return games;
	}

}
